package com.example.config;

import com.alibaba.fastjson.JSONObject;
import com.example.entity.RestBean;
import com.example.service.AuthorizeService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.sql.DataSource;
import java.io.IOException;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Resource
    AuthorizeService authorizeService;

    @Resource
    DataSource dataSource;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http,
                                           PersistentTokenRepository repository) throws Exception {
        return http
                .authorizeHttpRequests()
                .requestMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/api/auth/login")
                .successHandler(this::onAuthenticationSuccess)
                .failureHandler(this::onAuthenticationFailure)
                .and()
                .logout()
                .logoutUrl("/api/auth/logout")
                .logoutSuccessHandler(this::onAuthenticationSuccess)
                .and()
                .rememberMe()
                .rememberMeParameter("remember")
                .tokenRepository(repository)
                .tokenValiditySeconds(3600 * 24 * 7)
                .and()
                .csrf()
                .disable()
                .cors()
                .configurationSource(this.corsConfigurationSource())
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(this::onAuthenticationFailure)
                .and()
                .build();
    }

    @Bean
    public PersistentTokenRepository tokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(false);
        return jdbcTokenRepository;
    }

    private CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration cors = new CorsConfiguration();
        cors.addAllowedOriginPattern("*");
        cors.setAllowCredentials(true);
        cors.addAllowedHeader("*");
        cors.addAllowedMethod("*");
        cors.addExposedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", cors);
        return source;
    }

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity security) throws Exception {
        return security
                .getSharedObject(AuthenticationManagerBuilder.class)
                .userDetailsService(authorizeService)
                .and()
                .build();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        response.setCharacterEncoding("utf-8");
        if(request.getRequestURI().endsWith("/login"))
            response.getWriter().write(JSONObject.toJSONString(RestBean.success("登录成功")));
        else if(request.getRequestURI().endsWith("/logout"))
            response.getWriter().write(JSONObject.toJSONString(RestBean.success("退出登录成功")));
    }

    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        response.setCharacterEncoding("utf-8");
        response.getWriter().write(JSONObject.toJSONString(RestBean.failure(401, exception.getMessage())));
    }
}



// error
//package com.example.config;
//
//import com.alibaba.fastjson.JSONObject;
//import com.example.entity.RestBean;
//import com.example.service.AuthorizeService;
//import jakarta.annotation.Resource;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.security.authentication.AuthenticationManager;
//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//import org.springframework.security.web.SecurityFilterChain;
//import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
//import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
//import org.springframework.web.cors.CorsConfiguration;
//import org.springframework.web.cors.CorsConfigurationSource;
//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
//
//import javax.sql.DataSource;
//import java.io.IOException;
//
//@Configuration
//@EnableWebSecurity
//public class SecurityConfiguration {
//
//    @Resource
//    AuthorizeService authorizeService;
//
//    @Resource
//    DataSource dataSource;
//
//    @Bean
//    public SecurityFilterChain filterChain(HttpSecurity http,
//                                           PersistentTokenRepository repository) throws Exception {
//        return http
//                .authorizeHttpRequests()
//                .anyRequest().authenticated()
//                .and()
//                .formLogin()
//                .loginProcessingUrl("/api/auth/login")
//                .successHandler(this::onAuthenticationSuccess)
//                .failureHandler(this::onAuthenticationFailure)
//                .and()
//                .logout()
//                .logoutUrl("/api/auth/logout")
//                .logoutSuccessHandler(this::onAuthenticationSuccess)
//                .and()
//                .rememberMe()
//                .rememberMeParameter("remember")
//                .tokenRepository(repository)
//                .tokenValiditySeconds(3600*24*3)
//                .and()
//                .csrf()
//                .disable()
//                .cors()
//                .configurationSource(this.corsConfigurationSource())
//                .and()
//                .exceptionHandling()
//                .authenticationEntryPoint(this::onAuthenticationFailure)
//                .and()
//                .build();
//    }
//
//    @Bean
//    public PersistentTokenRepository tokenRepository() {
//        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
//        jdbcTokenRepository.setDataSource(dataSource);
//        jdbcTokenRepository.setCreateTableOnStartup(false);
//        return jdbcTokenRepository;
//    }
//
//    // 跨域配置源
//    private CorsConfigurationSource corsConfigurationSource() {
//        CorsConfiguration cors = new CorsConfiguration();
//        cors.addAllowedOriginPattern("*");
//        cors.setAllowCredentials(true);
//        cors.addAllowedHeader("*");
//        cors.addAllowedMethod("*");
//        cors.addExposedHeader("*");
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        source.registerCorsConfiguration("/**",cors);
//        return source;
//    }
//
//    @Bean
//    public AuthenticationManager authenticationManager(HttpSecurity security) throws Exception {
//        return security
//                .getSharedObject(AuthenticationManagerBuilder.class)
//                .userDetailsService(authorizeService)
//                .and()
//                .build();
//    }
//
//    @Bean
//    public BCryptPasswordEncoder passwordEncoder() {
//        return new BCryptPasswordEncoder();
//    }
//
//    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
//        response.setCharacterEncoding("utf-8");
//        if(request.getRequestURI().endsWith("/login"))
//            response.getWriter().write(JSONObject.toJSONString(RestBean.success("登录成功")));
//        else if(request.getRequestURI().endsWith("/logout"))
//            response.getWriter().write(JSONObject.toJSONString(RestBean.success("退出登录成功")));
//    }
//
//    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
//        response.setCharacterEncoding("utf-8");
//        response.getWriter().write(JSONObject.toJSONString(RestBean.failure(401, exception.getMessage())));
//    }
//}

// --------------------------------------

//errror
//import com.alibaba.fastjson.JSONObject;
//import com.example.entity.RestBean;
//import com.example.service.AuthorizeService;
//import jakarta.annotation.Resource;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.security.authentication.AuthenticationManager;
//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//import org.springframework.security.web.SecurityFilterChain;
//import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
//import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
//import org.springframework.web.cors.CorsConfiguration;
//import org.springframework.web.cors.CorsConfigurationSource;
//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
//
//import javax.sql.DataSource;
//import java.io.IOException;
//
//@Configuration
//@EnableWebSecurity
//public class SecurityConfiguration {
//
//    @Resource
//    AuthorizeService authorizeService;
//
//    @Resource
//    DataSource dataSource;
//
//    @Bean
//    public SecurityFilterChain filterChain(HttpSecurity http,
//                                           PersistentTokenRepository repository) throws Exception {
//        // 配置请求授权规则
//        http.authorizeHttpRequests(authorize -> authorize
//                .requestMatchers("/api/auth/**").permitAll()
//                .anyRequest().authenticated()
//        );
//
//        // 配置登录相关逻辑
//        http.formLogin(formLogin -> formLogin
//                .loginProcessingUrl("/api/auth/login")
//                .successHandler(this::onAuthenticationSuccess)
//                .failureHandler(this::onAuthenticationFailure)
//        );
//
//        // 配置注销相关逻辑
//        http.logout(logout -> logout
//                .logoutUrl("/api/auth/logout")
//                .logoutSuccessHandler(this::onLogoutSuccess)
//        );
//
//        // 配置记住我功能
//        http.rememberMe(rememberMe -> rememberMe
//                .rememberMeParameter("remember")
//                .tokenRepository(repository)
//                .tokenValiditySeconds(3600 * 24 * 7)
//        );
//
//        // 禁用 CSRF 防护（根据实际需求决定是否禁用，若有跨站请求场景需谨慎处理）
////        http.csrf(AbstractHttpConfigurer::disable);
//
//        // 配置跨域相关（可根据实际情况进行详细配置）
//        http.cors(cors -> cors.configurationSource(this.corsConfigurationSource()));
//
//        // 配置异常处理（可按需完善具体的异常处理逻辑）
//        http.exceptionHandling(exceptionHandling -> exceptionHandling
//                .authenticationEntryPoint(this::onAuthenticationFailure)
//        );
//
//        return http.build();
//    }
//
//    // 以下其余方法保持不变，如 tokenRepository、corsConfigurationSource、authenticationManager、passwordEncoder 等方法
//
//    // 登录成功处理逻辑示例，可根据实际需求调整
//    private void onAuthenticationSuccess(HttpServletRequest request,
//                                         HttpServletResponse response,
//                                         Authentication authentication) throws IOException {
//        response.setCharacterEncoding("utf-8");
//        if (request.getRequestURI().endsWith("/login"))
//            response.getWriter().write(JSONObject.toJSONString(RestBean.success("登录成功")));
//    }
//
//    // 登录失败处理逻辑示例，可根据实际需求调整
//    private void onAuthenticationFailure(HttpServletRequest request,
//                                         HttpServletResponse response,
//                                         AuthenticationException exception) throws IOException {
//        response.setCharacterEncoding("utf-8");
//        response.getWriter().write(JSONObject.toJSONString(RestBean.failure(401, exception.getMessage())));
//    }
//
//    // 注销成功处理逻辑示例，可根据实际需求调整
//    private void onLogoutSuccess(HttpServletRequest request,
//                                 HttpServletResponse response,
//                                 Authentication authentication) throws IOException {
//        response.setCharacterEncoding("utf-8");
//        response.getWriter().write(JSONObject.toJSONString(RestBean.success("退出登录成功")));
//    }
//
//    private CorsConfigurationSource corsConfigurationSource() {
//        CorsConfiguration cors = new CorsConfiguration();
//        cors.addAllowedOriginPattern("*");
//        cors.setAllowCredentials(true);
//        cors.addAllowedHeader("*");
//        cors.addAllowedMethod("*");
//        cors.addExposedHeader("*");
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        source.registerCorsConfiguration("/**", cors);
//        return source;
//    }
//
//    @Bean
//    public PersistentTokenRepository tokenRepository() {
//        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
//        jdbcTokenRepository.setDataSource(dataSource);
//        jdbcTokenRepository.setCreateTableOnStartup(false);
//        return jdbcTokenRepository;
//    }
//
//    @Bean
//    public AuthenticationManager authenticationManager(HttpSecurity security) throws Exception {
//        return security
//                .getSharedObject(AuthenticationManagerBuilder.class)
//                .userDetailsService(authorizeService)
//                .and()
//                .build();
//    }
//
//    @Bean
//    public BCryptPasswordEncoder passwordEncoder() {
//        return new BCryptPasswordEncoder();
//    }
//}